﻿<template>

  <div class="role-management">

    <div class="title-section">

      <h2>角色管理</h2>

      <button class="btn-primary" @click="onCreate">新建</button>

    </div>

    <!-- 筛选区域 -->
    <div class="controls-section">
      <div class="filters">
        <div class="filter-item">
          <label>关键词</label>
          <input type="text" placeholder="请输入关键词" v-model="query.keyword">
        </div>
        <div class="filter-item">
          <label>状态</label>
          <select v-model.number="query.status">
            <option value="">请选择</option>
            <option :value="1">启用</option>
            <option :value="0">停用</option>
          </select>
        </div>
      </div>
      <div class="actions">
        <button class="btn-primary" @click="onSearch" :disabled="loading">搜索</button>
        <button class="btn-secondary" @click="onReset" :disabled="loading">重置</button>
      </div>
    </div>

    <!-- 表格 -->
    <div class="table-section">
      <table>
        <thead>
        <tr>
          <th><input type="checkbox" v-model="selectAll" @change="toggleSelectAll"></th>
          <th>角色编号</th>
          <th>角色名称</th>
          <th>角色描述</th>
          <th>员工数</th>
          <th>启用状态</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="(record, idx) in tableData" :key="record.roleId || idx" v-if="!loading">
          <td><input type="checkbox" v-model="record.selected" @change="updateSelectAll"></td>
          <td class="link-style" @click="openDetail(record)">{{ record.roleCode || '-' }}</td>
          <td>{{ record.roleName || '-' }}</td>
          <td>{{ record.description || '-' }}</td>
          <td>{{ record.number || 0 }}</td>
          <td :class="{ 'status-enable': record.status === 1, 'status-disable': record.status !== 1 }">
            {{ record.status === 1 ? '启用' : '停用' }}
          </td>
        </tr>
        <tr v-if="loading">
          <td colspan="6" style="text-align: center; padding: 40px;">加载中...</td>
        </tr>
        <tr v-if="!loading && tableData.length === 0">
          <td colspan="6" style="text-align: center; padding: 40px; color: #999;">暂无数据</td>
        </tr>
        </tbody>
      </table>
    </div>

    <!-- 底部分页和操作 -->
    <div class="footer-section">
      <div class="footer-left">
        <input type="checkbox" v-model="selectAll" @change="toggleSelectAll">
        <label>全选</label>
        <button class="btn-secondary" @click="exportSelected">导出</button>
      </div>
      <div class="pagination">
        <button @click="prevPage" :disabled="currentPage === 1">&lt;</button>
        <button v-for="page in totalPages" :key="page" :class="{ active: currentPage === page }" @click="goToPage(page)">{{ page }}</button>
        <button @click="nextPage" :disabled="currentPage === totalPages">&gt;</button>
        <select v-model.number="pageSize" @change="onPageSizeChange">
          <option value="10">10条/页</option>
          <option value="20">20条/页</option>
        </select>
      </div>
    </div>

    <!-- 详情弹窗 -->
    <a-modal
      v-model:visible="detailDialogVisible"
        title="角色详情"
      :width="700"
      :footer="null"
      @cancel="closeDetail"
    >
      <a-spin :spinning="detailLoading">
        <div v-if="!detailLoading && Object.keys(detail).length > 0">
          <!-- 角色基本信息卡片 -->
          <div class="detail-card">
            <div class="detail-header">
              <div class="detail-title">
                <span class="detail-code-large">{{ detail.roleCode || '-' }}</span>
                <span class="detail-name-large">{{ detail.roleName || '-' }}</span>
                <a-tag :color="detail.status === 1 ? 'success' : 'error'" class="detail-status-tag">
                {{ detail.status === 1 ? '启用' : '停用' }}
              </a-tag>
              </div>
              <div class="detail-actions-top">
                <a-space>
                  <a-button type="primary" size="small" @click="editFromDetail">编辑</a-button>
                  <a-popconfirm 
                    title="确认删除该角色？" 
                    ok-text="删除" 
                    ok-type="danger" 
                    cancel-text="取消" 
                    @confirm="deleteFromDetail"
                  >
                    <a-button danger size="small">删除</a-button>
                  </a-popconfirm>
                </a-space>
              </div>
              </div>
            </div>

          <!-- 详细信息 -->
          <div class="detail-content">
            <a-row :gutter="16">
              <a-col :span="12">
                <div class="detail-item">
                  <div class="detail-label">角色ID</div>
                  <div class="detail-value">{{ detail.roleId || '-' }}</div>
                </div>
              </a-col>
              <a-col :span="12">
                <div class="detail-item">
                  <div class="detail-label">员工数</div>
                  <div class="detail-number">{{ detail.number ?? '-' }}</div>
                </div>
              </a-col>
            </a-row>
            
            <a-row :gutter="16">
              <a-col :span="12">
                <div class="detail-item">
                  <div class="detail-label">创建时间</div>
                  <div class="detail-time">{{ formatTime(detail.createTime) || '-' }}</div>
                </div>
              </a-col>
              <a-col :span="12">
                <div class="detail-item">
                  <div class="detail-label">更新时间</div>
                  <div class="detail-time">{{ formatTime(detail.updateTime) || '-' }}</div>
                </div>
              </a-col>
            </a-row>

            <div class="detail-item detail-item-full">
              <div class="detail-label">角色描述</div>
              <div class="detail-description">{{ detail.description || '暂无描述' }}</div>
            </div>
          </div>
            </div>

        <!-- 空状态 -->
        <div v-if="!detailLoading && Object.keys(detail).length === 0" class="detail-empty">
          <a-empty description="未找到角色信息" />
            </div>
          </a-spin>
    </a-modal>

    <!-- 编辑对话框 -->
    <a-modal
       v-model:visible="editDialogVisible"
        :title="isCreateMode ? '新建角色' : '编辑角色'"
        @ok="onSave"
        @cancel="editDialogVisible = false"
        :confirm-loading="editLoading"
    >
      <a-form :model="editForm" layout="vertical">
        <a-form-item label="角色名称" required>
          <a-input v-model:value="editForm.roleName" placeholder="请输入角色名称" />
        </a-form-item>
        <a-form-item label="角色描述">
          <a-textarea v-model:value="editForm.description" placeholder="请输入角色描述" :rows="3" />
        </a-form-item>
        <a-form-item label="员工数">
          <a-input-number v-model:value="editForm.number" :min="0" placeholder="请输入员工数" style="width: 100%" />
        </a-form-item>
        <a-form-item label="状态">
          <a-radio-group v-model:value="editForm.status">
            <a-radio :value="1">启用</a-radio>
            <a-radio :value="0">停用</a-radio>
          </a-radio-group>
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script>
import { message } from 'ant-design-vue'
import * as XLSX from 'xlsx'
import {
  pageRoles,
  getRoleDetail,
  createRole,
  updateRole,
  deleteRole
} from '@/api/role'

export default {
  name: 'RoleManagement',
  data() {
    return {
      loading: false,
      query: { keyword: '', status: '' },
      // 分页
      currentPage: 1,
      pageSize: 10,
      total: 0,
      totalPages: 1,
      // 表格
      tableData: [],
      selectedRowKeys: [],
      selectAll: false,
      // 详情
      detailDialogVisible: false,
      detail: {},
      detailLoading: false,
      // 编辑
      editDialogVisible: false,
      editLoading: false,
      editForm: { roleId: null, roleName: '', description: '', number: 0, status: 1 },
      isCreateMode: false,
    }
  },
  computed: {
    rowSelection() {
      return {
        selectedRowKeys: this.selectedRowKeys,
        onChange: (keys) => { this.selectedRowKeys = keys }
      }
    }
  },
  created() { 
    this.fetchData() 
  },
  methods: {
    exportSelected() {
      const selected = this.tableData.filter(r => r.selected)
      if (selected.length === 0) {
        alert('请选择要导出的数据')
        return
      }
      const rows = selected.map(r => ({
        '角色编号': r.roleCode || '',
        '角色名称': r.roleName || '',
        '角色描述': r.description || '',
        '员工数': r.number ?? '',
        '启用状态': r.status === 1 ? '启用' : '停用'
      }))
      const ws = XLSX.utils.json_to_sheet(rows)
      const wb = XLSX.utils.book_new()
      XLSX.utils.book_append_sheet(wb, ws, '角色')
      const date = new Date().toISOString().slice(0, 10)
      XLSX.writeFile(wb, `角色_导出_${date}.xlsx`)
    },

    async fetchData() {
      this.loading = true
      try {
        const res = await pageRoles({
          pageNum: this.currentPage,
          pageSize: this.pageSize,
          keyword: this.query.keyword || undefined,
          status: this.query.status !== '' ? this.query.status : undefined
        })
        const data = res?.data?.data || {}
        this.tableData = (data.records || []).map(item => ({ 
          ...item,
          selected: false 
        }))
        this.total = data.total || 0
        this.totalPages = Math.max(1, Math.ceil(this.total / this.pageSize))
        this.currentPage = data.current || 1
        this.pageSize = data.size || 10
        this.updateSelectAll()
      } catch (error) {
        console.error('获取数据失败', error)
        message.error('获取数据失败')
      } finally {
        this.loading = false
      }
    },

    onTableChange(pagination) {
      const { current, pageSize } = pagination
      this.currentPage = current
      this.pageSize = pageSize
      this.fetchData()
    },

    // 新增的分页和选择方法
    toggleSelectAll() { 
      this.tableData.forEach(r => { r.selected = this.selectAll; }); 
    },
    
    updateSelectAll() { 
      this.selectAll = this.tableData.length > 0 && this.tableData.every(r => r.selected); 
    },
    
    prevPage() { 
      if (this.currentPage > 1) { 
        this.currentPage--; 
        this.fetchData() 
      } 
    },
    
    nextPage() { 
      if (this.currentPage < this.totalPages) { 
        this.currentPage++; 
        this.fetchData() 
      } 
    },
    
    goToPage(page) { 
      if (page !== this.currentPage) { 
        this.currentPage = page; 
        this.fetchData() 
      } 
    },

    onPageSizeChange() { 
      this.currentPage = 1; 
      this.fetchData()
    },

    onSearch() {
      this.currentPage = 1
      this.fetchData()
    },

    onReset() {
      this.query = { keyword: '', status: '' }
      this.currentPage = 1
      this.fetchData()
    },

    async openDetail(row) {
      if (!row || !row.roleId) {
        message.error('角色信息不完整')
        return
      }
      
      this.detailLoading = true
      this.detailDialogVisible = true
      this.detail = {} // 先清空详情
      
      try {
        const res = await getRoleDetail(row.roleId)
        const data = res?.data?.data
        
        if (data) {
          this.detail = {
            ...data,
            // 确保必要字段存在
            roleId: data.roleId || row.roleId,
            roleCode: data.roleCode || row.roleCode,
            roleName: data.roleName || row.roleName,
            description: data.description || row.description,
            number: data.number ?? row.number ?? 0,
            status: data.status ?? row.status ?? 0
          }
        } else {
          // 如果后端没有返回数据，使用行数据作为后备
          this.detail = { ...row }
          message.warning('获取详细信息失败，显示基本信息')
        }
      } catch (error) {
        console.error('获取角色详情失败', error)
        message.error('获取角色详情失败')
        // 使用行数据作为后备
        this.detail = { ...row }
      } finally {
        this.detailLoading = false
      }
    },

    closeDetail() {
      this.detailDialogVisible = false
      this.detail = {}
      this.detailLoading = false
    },

    // 从详情页面编辑
    editFromDetail() {
      if (!this.detail || !this.detail.roleId) {
        message.error('角色信息不完整')
        return
      }
      this.onEdit(this.detail)
    },

    // 从详情页面删除
    async deleteFromDetail() {
      if (!this.detail || !this.detail.roleId) {
        message.error('角色信息不完整')
        return
      }
      
      try {
        await deleteRole(this.detail.roleId)
        message.success('删除成功')
        this.closeDetail()
        // 刷新列表
        this.fetchData()
      } catch (error) {
        console.error('删除失败', error)
        message.error('删除失败')
      }
    },

    // 格式化时间
    formatTime(time) {
      if (!time) return ''
      try {
        const date = new Date(time)
        if (isNaN(date.getTime())) return time
        return date.toLocaleString('zh-CN', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
          second: '2-digit'
        })
      } catch (error) {
        return time
      }
    },

    onCreate() {
      this.isCreateMode = true
      this.editForm = { roleId: null, roleName: '', description: '', number: 0, status: 1 }
      this.editDialogVisible = true
    },

    async onEdit(row) {
      // 打开编辑弹窗并预填数据（优先用详情接口）
      try {
        const res = await getRoleDetail(row.roleId)
        const d = res?.data?.data || row || {}
        this.isCreateMode = false
        this.editForm = {
          roleId: d.roleId,
          roleName: d.roleName || '',
          description: d.description || '',
          number: d.number ?? 0,
          status: d.status ?? 1
        }
        this.editDialogVisible = true
      } catch (e) {
        console.error('获取角色详情失败', e)
        // 回退：直接用表格行数据
        const d = row || {}
        this.isCreateMode = false
        this.editForm = {
          roleId: d.roleId,
          roleName: d.roleName || '',
          description: d.description || '',
          number: d.number ?? 0,
          status: d.status ?? 1
        }
        this.editDialogVisible = true
      }
    },

    async onDelete(row) {
      try {
        await deleteRole(row.roleId)
        message.success('删除成功')
        // 从列表中移除，避免重复请求时闪烁，也可直接 refetch
        this.tableData = this.tableData.filter(r => r.roleId !== row.roleId)
        this.total = Math.max(0, this.total - 1)
        // 如果当前页被删空，回退一页再拉取
        if (this.tableData.length === 0 && this.currentPage > 1) {
          this.currentPage -= 1
          this.fetchData()
        }
      } catch (e) {
        console.error('删除失败', e)
        message.error('删除失败')
      }
    },

    async onSave() {
      if (!this.editForm.roleName?.trim()) {
        message.error('请输入角色名称')
        return
      }
      this.editLoading = true
      try {
        if (this.isCreateMode) {
          await createRole(this.editForm)
        } else {
          await updateRole(this.editForm)
        }
        this.editDialogVisible = false
        this.fetchData()
      } catch (error) {
        console.error('保存失败', error)
      } finally {
        this.editLoading = false
      }
    },

  }
}
</script>

<style scoped>
.role-management { padding: 20px; background-color: #f5f7fa; }
.title-section { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
.title-section h2 { font-size: 20px; font-weight: bold; }

.controls-section { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 20px; background-color: #fff; border-radius: 8px; margin-bottom: 20px; align-items: center; }
.filters { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }
.filter-item { display: flex; align-items: center; gap: 8px; }
.filter-item label { font-size: 14px; white-space: nowrap; }
.filter-item input, .filter-item select { padding: 8px; border: 1px solid #dcdfe6; border-radius: 4px; width: 150px; }
.actions { display: flex; gap: 10px; }

.btn-primary { background-color: #409eff; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; }
.btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-secondary { background-color: #fff; color: #606266; border: 1px solid #dcdfe6; padding: 8px 16px; border-radius: 4px; cursor: pointer; }

.table-section { background-color: #fff; padding: 20px; border-radius: 8px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ebeef5; }
th { background-color: #f8f9fa; }
.link-style { color: #409eff; cursor: pointer; }
.status-enable { color: #2eaa3b; }
.status-disable { color: #f44336; }

.footer-section { display: flex; justify-content: space-between; align-items: center; margin-top: 20px; background-color: #fff; padding: 10px 20px; border-radius: 8px; }
.footer-left { display: flex; align-items: center; gap: 8px; }
.pagination { display: flex; align-items: center; gap: 8px; }
.pagination button { padding: 6px 12px; border: 1px solid #dcdfe6; background-color: #fff; cursor: pointer; border-radius: 4px; }
.pagination button.active { background-color: #409eff; color: white; border-color: #409eff; }
.pagination button:disabled { opacity: 0.6; cursor: not-allowed; }
.pagination select { padding: 6px; border: 1px solid #dcdfe6; border-radius: 4px; }

/* 详情弹窗样式 */
.detail-card {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 20px;
}

.detail-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.detail-title {
  display: flex;
  align-items: center;
  gap: 12px;
}

.detail-code-large {
  font-family: 'Courier New', monospace;
  background: #409eff;
  color: white;
  padding: 6px 12px;
  border-radius: 6px;
  font-weight: bold;
  font-size: 16px;
}

.detail-name-large {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}

.detail-status-tag {
  font-size: 14px;
  padding: 4px 12px;
  border-radius: 12px;
}

.detail-actions-top {
  display: flex;
  gap: 8px;
}

.detail-content {
  background: white;
  border-radius: 8px;
  padding: 20px;
}

.detail-item {
  margin-bottom: 16px;
}

.detail-item-full {
  margin-top: 8px;
}

.detail-label {
  font-size: 12px;
  color: #909399;
  margin-bottom: 4px;
  font-weight: 500;
}

.detail-value { 
  font-weight: 500; 
  color: #303133; 
  font-size: 14px;
}

.detail-code { 
  font-family: 'Courier New', monospace; 
  background: #f5f7fa; 
  padding: 2px 6px; 
  border-radius: 3px; 
  color: #409eff; 
  font-weight: 600;
}

.detail-name { 
  font-weight: 600; 
  color: #303133; 
  font-size: 14px;
}

.detail-number { 
  font-weight: 500; 
  color: #606266; 
  font-size: 14px;
}

.detail-time { 
  color: #909399; 
  font-size: 13px; 
}

.detail-description { 
  color: #606266; 
  line-height: 1.6; 
  min-height: 20px;
  white-space: pre-wrap;
  background: #f8f9fa;
  padding: 12px;
  border-radius: 6px;
  border-left: 4px solid #409eff;
}

.detail-empty { 
  display: flex; 
  justify-content: center; 
  align-items: center; 
  min-height: 200px; 
}

/* 链接样式优化 */
.link-style:hover { 
  text-decoration: underline; 
  color: #66b1ff; 
}

/* 表格行悬停效果 */
tbody tr:hover {
  background-color: #f5f7fa;
}

</style>
